// Copyright (C) 2025, ZWSOFT Co., LTD.(Guangzhou)
// Licensed under the MIT License. See LICENSE in the project root for license information.

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TestClient.Domain;

namespace TestClient.ViewModel;
public partial class LoopOperationTestViewModel : PageViewModelBase
{
    [ObservableProperty]
    private string surfaceId = string.Empty;
    [ObservableProperty]
    private string boundaryId = string.Empty;
    [ObservableProperty]
    private string splitCurve1 = string.Empty;
    [ObservableProperty]
    private string splitCurve2 = string.Empty;
    [ObservableProperty]
    private string locatePoint = string.Empty;

    [ObservableProperty]
    private string boundCurves = string.Empty;
    private List<string> boundCurveList = [];

    [ObservableProperty]
    private string resultId = string.Empty;
    [ObservableProperty]
    private string newBoundaryId = string.Empty;
    [ObservableProperty]
    private string newSurfaceId = string.Empty;

    public IAsyncRelayCommand SelectSurfaceCommand { get; }
    public IAsyncRelayCommand SelectBoundaryCommand { get; }
    public IAsyncRelayCommand SelectSplitCurve1Command { get; }
    public IAsyncRelayCommand SelectSplitCurve2Command { get; }
    public IAsyncRelayCommand SelectLocatePointCommand { get; }
    public IAsyncRelayCommand SelectMultipleCurveCommand { get; }

    public IAsyncRelayCommand SplitSurfaceCommand { get; }
    public IAsyncRelayCommand SplitSurface2Command { get; }
    public IAsyncRelayCommand ExtractLoopCommand { get; }
    public IAsyncRelayCommand ExtendLoopCommand { get; }

    public LoopOperationTestViewModel(VFAdapterWrapper wrapper, ISnackNotifyService notifyService) : base(wrapper, notifyService)
    {
        SelectSurfaceCommand = CreateAsyncRpcCommand(SelectSurface);
        SelectBoundaryCommand = CreateAsyncRpcCommand(SelectBoundary);
        SelectSplitCurve1Command = CreateAsyncRpcCommand(SelectSplitCurve1);
        SelectSplitCurve2Command = CreateAsyncRpcCommand(SelectSplitCurve2);
        SelectLocatePointCommand = CreateAsyncRpcCommand(SelectLocatePoint);
        SelectMultipleCurveCommand = CreateAsyncRpcCommand(SelectMultipleCurve);

        SplitSurfaceCommand = CreateAsyncRpcCommand(SplitSurface);
        SplitSurface2Command = CreateAsyncRpcCommand(SplitSurface2);
        ExtractLoopCommand = CreateAsyncRpcCommand(ExtractLoop);
        ExtendLoopCommand = CreateAsyncRpcCommand(ExtendLoopAsync);
    }

    private async Task SelectSurface()
    {
        EnsureConnected();
        SurfaceId = await ViewModelHelpers.SelectEnt(Wrapper, "Surface");
    }

    private async Task SelectBoundary()
    {
        EnsureConnected();
        BoundaryId = await ViewModelHelpers.SelectEnt(Wrapper, "Curve");
    }

    private async Task SelectSplitCurve1()
    {
        EnsureConnected();
        SplitCurve1 = await ViewModelHelpers.SelectEnt(Wrapper, "Curve");
    }

    private async Task SelectSplitCurve2()
    {
        EnsureConnected();
        SplitCurve2 = await ViewModelHelpers.SelectEnt(Wrapper, "Curve");
    }
    private async Task SelectLocatePoint()
    {
        EnsureConnected();
        LocatePoint = await ViewModelHelpers.SelectEnt(Wrapper, "Point");
    }
    private async Task SelectMultipleCurve()
    {
        EnsureConnected();
        var curves = await Task.Run(() =>
        {
            return Wrapper.MultiSelect("Curve");
        });
        if (curves is null)
            return;
        boundCurveList = curves;
        BoundCurves = string.Join(", ", curves);
    }
    private async Task SplitSurface()
    {
        EnsureConnected();
        ResultId = await Task.Run(() =>
        {
            var coord = Wrapper.GetPointCoord(LocatePoint);
            return Wrapper.GetBoundaryIDbyDivide(BoundaryId, SurfaceId, coord, SplitCurve1, null);
        });
    }
    private async Task SplitSurface2()
    {
        EnsureConnected();
        ResultId = await Task.Run(() =>
        {
            var coord = new Vector3d();
            return Wrapper.GetBoundaryIDbyDivide(BoundaryId, SurfaceId, coord, SplitCurve1, SplitCurve2);
        });
    }
    private async Task ExtractLoop()
    {
        EnsureConnected();
        (NewBoundaryId, NewSurfaceId) = await Task.Run(() =>
        {
            var coord = Wrapper.GetPointCoord(LocatePoint);
            return Wrapper.GetBoundaryIDByPoint(BoundaryId, SurfaceId, [.. boundCurveList], coord);
        });
    }
    private async Task ExtendLoopAsync()
    {
        EnsureConnected();
        var newBoundaryId = await Task.Run(() =>
        {
            var coord = Wrapper.GetPointCoord(LocatePoint);
            return Wrapper.GetNewBoundary(BoundaryId, SplitCurve1, coord);
        });
        ResultId = newBoundaryId;
    }
}
